/**
 * 客户端系统管理员模型
 *
 * Created by snowingsea on 2020/01/22.
 */
const fs = require('fs');
const request = require('request-promise');
const querystring = require('querystring');
const { roleKind, statusKind } = require('./../../phoenix/models/users');
const User = require('./user');
const Tester = require('./tester');

const administratorURI = require('./../api/administrator/uri');
const { sampleManager } = require('./../../phoenix/config');

class Administrator extends User {
  constructor(username = sampleManager.username, password = sampleManager.password) {
    super(username, password);
  }

  /**
   * 获取用户信息
   * @param {String} userId 用户id
   * @return {Promise}
   */
  getUser(userId) {
    return new Promise((resolve, reject) => {
      let user;
      this.login()
        .then(() => {
          const options = {
            url: `${administratorURI}/users/${userId}.json`,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
            json: true,
          };
          return request.get(options);
        })
        .then((res) => {
          user = res;
          return this.logout();
        })
        .then(() => {
          resolve(user);
        })
        .catch(reject);
    });
  }

  /**
   * 获取所有用户列表
   * @return {Promise}
   */
  getAllUsers() {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          let page = 1;
          const allUsers = [];
          const that = this;
          function step() {
            request.get({
              url: `${administratorURI}/users.json?page=${page}`,
              headers: { Authorization: `Bearer ${that.token.accessToken}` },
              json: true,
            })
              .then(({ users }) => {
                if (users.length === 0) {
                  that.logout().then(() => { resolve(allUsers); }).catch(reject);
                  return;
                }
                page += 1;
                users.forEach((info) => {
                  const {
                    userId,
                    username,
                    nickname,
                    status,
                    role,
                    lang,
                  } = info;
                  const user = new User(username);
                  user.userId = userId;
                  user.nickname = nickname;
                  user.status = status;
                  user.role = role;
                  user.lang = lang;
                  allUsers.push(user);
                });
                step();
              })
              .catch(reject);
          }
          step();
        })
        .catch(reject);
    });
  }

  /**
   * 登录状态下创建用户
   * @param {String} username 用户名
   * @param {String} password 密码
   * @param {Array|Number} roles 角色
   * @param {String} lang 前使用语言
   * @param {String} nickname 昵称
   * @return {Promise}
   */
  createUser({ username, password, roles, lang, nickname = undefined }) { // eslint-disable-line
    return new Promise((resolve, reject) => {
      const user = new User(username);
      user.password = password;
      const form = {
        username,
        password,
        roles,
        lang,
      };
      if (nickname) {
        form.nickname = nickname;
      }
      const options = {
        url: `${administratorURI}/users.json`,
        headers: { Authorization: `Bearer ${this.token.accessToken}` },
        form,
        json: true,
      };
      request.post(options)
        .then((res) => {
          const {
            userId,
            nickname,
            status,
            role,
            lang,
          } = res;
          user.userId = userId;
          user.nickname = nickname;
          user.status = status;
          user.role = role;
          user.lang = lang;
          resolve(user);
        })
        .catch(reject);
    });
  }

  /**
   * 创建随机用户
   * @return {Promise}
   */
  createRandomUser() {
    return new Promise((resolve, reject) => {
      let user;
      this.login()
        .then(() => this.createUser(User.getRandomUserInfo()))
        .then((res) => {
          user = res;
          return this.logout();
        })
        .then(() => {
          resolve(user);
        })
        .catch(reject);
    });
  }

  /**
   * 创建测试人员
   * @return {Promise}
   */
  createRandomTester() {
    return new Promise((resolve, reject) => {
      const userInfo = User.getRandomUserInfo();
      userInfo.roles = roleKind.tester;
      let tester;
      this.login()
        .then(() => this.createUser(userInfo))
        .then(({ username, password, userId }) => {
          tester = new Tester(username);
          tester.password = password;
          tester.userId = userId;
          return this.logout();
        })
        .then(() => {
          resolve(tester);
        })
        .catch(reject);
    });
  }

  /**
   * 创建管理人员
   * @return {Promise}
   */
  createRandomAdministrator() {
    return new Promise((resolve, reject) => {
      const userInfo = User.getRandomUserInfo();
      userInfo.roles = roleKind.administrator;
      let administrator;
      this.login()
        .then(() => this.createUser(userInfo))
        .then(({ username, password, userId }) => {
          administrator = new Administrator(username);
          administrator.password = password;
          administrator.userId = userId;
          return this.logout();
        })
        .then(() => {
          resolve(administrator);
        })
        .catch(reject);
    });
  }

  /**
   * 批量创建随机用户
   * @param {Number} count 创建个数
   * @return {Promise}
   */
  createRandomUsers(count = 10) {
    return new Promise((resolve, reject) => {
      let users;
      this.login()
        .then(() => {
          const promises = [];
          for (let i = 0; i < count; i += 1) {
            promises.push(this.createUser(User.getRandomUserInfo()));
          }
          return Promise.all(promises);
        })
        .then((res) => {
          users = res;
          return this.logout();
        })
        .then(() => {
          resolve(users);
        })
        .catch(reject);
    });
  }

  /**
   * 删除用户
   * @param {String} userId 用户id
   * @return {Promise}
   */
  removeUser(userId) {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const url = `${administratorURI}/users/${userId}.json`;
          return request.delete({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
          });
        })
        .then(() => this.logout())
        .then(() => {
          resolve();
        })
        .catch(reject);
    });
  }

  /**
   * 批量删除用户
   * @param {Array} userIds 用户id列表
   * @return {Promise}
   */
  removeUsers(userIds) {
    if (!userIds || userIds.length === 0) {
      return Promise.resolve();
    }
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const url = `${administratorURI}/users.json?${querystring.stringify({ userIds })}`;
          return request.delete({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
          });
        })
        .then(() => this.logout())
        .then(() => {
          resolve();
        })
        .catch(reject);
    });
  }

  /**
   * 更新用户信息
   * @param {String} userId 用户id
   * @param {Object} options 更新信息
   * @return {Promise}
   */
  updateUser(userId, options) {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const url = `${administratorURI}/users/${userId}.json?${querystring.stringify(options)}`;
          return request.put({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
          });
        })
        .then(() => this.logout())
        .then(() => {
          resolve();
        })
        .catch(reject);
    });
  }

  /**
   * 随机改变用户状态
   * @param {Array} users 用户列表
   * @return {Promise}
   */
  randomUpdateStatus4Users(users) {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const statusArray = Object.keys(statusKind).map((key) => statusKind[key]);
          const promises = users.map((user) => {
            const status = statusArray[Math.floor(Math.random() * statusArray.length)];
            if (status === statusKind.online) {
              return user.login();
            }
            const url = `${administratorURI}/users/${user.userId}.json?${querystring.stringify({ status })}`;
            return request.put({
              url,
              headers: { Authorization: `Bearer ${this.token.accessToken}` },
            });
          });
          return Promise.all(promises);
        })
        .then(() => this.logout())
        .then(resolve)
        .catch(reject);
    });
  }

  /**
   * 获取用户总数
   * @return {Promise}
   */
  getUserTotalNumber() {
    return new Promise((resolve, reject) => {
      let totalNumber = 0;
      this.login()
        .then(() => {
          const url = `${administratorURI}/users.json`;
          return request.get({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
            json: true,
          });
        })
        .then(({ pagination }) => {
          totalNumber = pagination.total;
          return this.logout();
        })
        .then(() => {
          resolve(totalNumber);
        })
        .catch(reject);
    });
  }

  /**
   * 更换许可证
   * @param {Number} status 许可证状态
   * @return {Promise}
   */
  replaceLicense(status) {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const licensePath = `test/benchmark/license/${status}`;
          const url = `${administratorURI}/license.json`;
          return request.post({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
            json: true,
            formData: {
              file: fs.createReadStream(licensePath),
            },
          });
        })
        .then(resolve)
        .catch(reject);
    });
  }

  /**
   * 删除许可证
   * @return {Promise}
   */
  removeLicense() {
    return new Promise((resolve, reject) => {
      this.login()
        .then(() => {
          const url = `${administratorURI}/license.json`;
          return request.delete({
            url,
            headers: { Authorization: `Bearer ${this.token.accessToken}` },
          });
        })
        .then(resolve)
        .catch(reject);
    });
  }
}

/**
 * Export model definition object.
 */
module.exports = Administrator;
